#ifndef SPL_WNDBASE
#define SPL_WNDBASE

#define SPL_WNDCLASS     _T("spl.window")
#define SPL_CHILDCLASS   _T("spl.child")

#ifndef WM_DWMCOMPOSITIONCHANGED
#define WM_DWMCOMPOSITIONCHANGED 0x031E
#endif

//! Class to handle common window messages and operations
class DLLEXPORT WndBase : public WrapWnd
{
private:
#pragma region Internal Declarations
  //! WPARAM parameter
  WPARAM _wParam;
  //! LPARAM parameter
  LPARAM _lParam;
#pragma endregion

#pragma region Internal Methods
  //! Initializes the window
  void initWindow();

  //! Default window procedure
  //! HWND:            window handle
  //! UINT:            message code
  //! WPARAM:          message's wParam
  //! LPARAM:          message's lParam
  static LRESULT CALLBACK defWndProc(HWND, UINT, WPARAM, LPARAM);
#pragma endregion

protected:
#pragma region Protected Methods
  //! Window specific procedure
  //! msg:		        message code
  //! wParam:		        message's wParam
  //! lParam:		        message's lParam
  //! lResult:            message result
  //! handled:            true if the message is handled
  virtual void wndProc(Event::WndProcEvent& iEvent);
#pragma endregion

#pragma region Misc Notifications
  //! Occurs when the notify icon is hovered, selected or clicked
  //! uID:                 notify icon identifier
  //! msg:                 mouse or keyboard message
  virtual void onNotifyIcon(Event::NotifyIconEvent& iEvent);

  //! Occurs when the taskbar has been created
  virtual void onTaskbarCreated();

  //! Occurs when a window timer interval is elapsed
  //! uID:                 timer id
  virtual void onTimer(Event::TimerEvent& iEvent);
#pragma endregion

#pragma region Device Management Notifications
  //! Occurs when the hardware configuration of a device has changed
  //! wEvent:              event type (any DBT_* value)
  //! pData:               pointer to a structure that contains specific
  //!                      information on the event
  virtual void onDeviceChange(Event::DeviceChangeEvent& iEvent);
#pragma endregion

#pragma region Menu Notifications
  //! Occurs when the user selects a command item from a menu,
  //! when a control sends a notification message to its parent window,
  //! or when an accelerator keystroke is translated<
  //! nCode:               notification code, 1 if accelerator, 0 if menu
  //! id:                  control identifier
  //! hWndControl:         control handle
  virtual void onCommand(Event::CommandEvent& iEvent);
#pragma endregion

#pragma region Desktop Window Management Notifications
  // unimplemented:
  //      WM_DWMCOLORIZATIONCOLORCHANGED, WM_DWMNCRENDERINGCHANGED,
  //      WM_DWMWINDOWMAXIMIZEDCHANGE,

  //#if (WINVER >= 0x0600)
  //! Occurs when the composition state has changed
  virtual void onCompositionChanged();
  //#endif
#pragma endregion

#pragma region Painting & Drawing Notifications
#ifndef COMMON_WM_ONLY
  //! Occurs after the display resolution has changed
  //! nBitsPerPixel:       image depth of the display
  //! width:               horizontal resolution
  //! height:              vertical resolution
  virtual void onDisplayChange(Event::DisplayChangeEvent& iEvent);
#endif
#pragma endregion

#pragma region Keyboard Notifications
  //! Occurs when the user presses a hotkey registered with this window
  //! id:              hotkey identifier
  //! fsModifiers:     hotkey modifiers
  //! vkCode:          hotkey virtual key code
  virtual void onHotKey(Event::HotkeyEvent& iEvent);
#pragma endregion

#pragma region Window Notifications
#ifndef COMMON_WM_ONLY
  //! Occurs when the user has logged on or off
  virtual void onUserChanged();

#if (WINVER >= 0x0501)
  //! Occurs when the window theme has changed
  virtual void onThemeChanged();
#endif

  //! Occurs before the window styles are changed by SetWindowLong
  //! nStyle:          specifies if the styles or extended styles are
  //!                  about to change (any GWLP_* value)
  //! pStyleStruct:    pointer to a STYLESTRUCT structure
  virtual void onStyleChanging(Event::StyleEvent& iEvent);

  //! Occurs after the window styles are changed by SetWindowLong
  //! nStyle:          specifies if the styles or extended styles are
  //!                  changed (any GWLP_* value)
  //! pStyleStruct:    pointer to a STYLESTRUCT structure
  virtual void onStyleChanged(Event::StyleEvent& iEvent);
#endif

  //! Occurs before the window gets destroyed
  virtual void onDestroy();
#pragma endregion

public:
#pragma region Accessors
  //! Gets the last window message WPARAM
  SPLINL WPARAM getLastWPARAM()
  {
    return _wParam;
  }
  //! Gets the last window message LPARAM
  SPLINL LPARAM getLastLPARAM()
  {
    return _lParam;
  }

  //! Returns the WndBase class associated with the given window handle
  static SPLINL WndBase* fromHandle(HWND handle)
  {
    return (WndBase*)GetWindowLong(handle, GWLP_USERDATA);
  }
#pragma endregion

#pragma region Construction
  //! Destroys this window
  virtual LRESULT destroy() { return WrapWnd::destroy(); }

  //! Window base destructor
  SPLINL virtual ~WndBase() { destroy(); }
#pragma endregion

#pragma region Friends
  friend class FrameWnd;
  friend class Dialog;
  friend class Window;
  friend class HiddenWnd;
  friend VOID SPLib::Windows::initWindows();
#pragma endregion
};

#endif